#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <functional>
#include "task.hpp"
#include "channel.hpp"

enum
{
    OK = 0,
    UsageError,
    PipeError,
    ForkError
};

using work_t = std::function<void()>;

class processpool
{
public:
    processpool(int n, work_t w)
        : _num(n), _work(w)
    {
    }

    int InitProcessPool()
    {
        for (int i = 0; i < _num; i++)
        {
            // 1.先建立管道
            int pipefd[2] = {0};
            int n = pipe(pipefd);
            if (n < 0)
            {
                return PipeError;
            }
            // 2.创建进程
            pid_t id = fork();
            if (id < 0)
            {
                return ForkError;
            }
            // 3.建立通信管道
            if (id == 0)
            {
                std::cout << getpid() << "关闭历史管道";
                for (auto &c : _channels)
                {
                    std::cout << c.Wfd() << " ";
                    c.Close();
                }
                std::cout << "over" << std::endl;

                ::close(pipefd[1]); // 关闭写端
                std::cout << "debug " << pipefd[0] << std::endl;

                dup2(pipefd[0], 0);
                _work();
                ::exit(0);
            }
            // 父进程
            ::close(pipefd[0]); // 关闭读端
            _channels.emplace_back(pipefd[1], id);
        }
        return OK;
    }

    void Dispatchtask()
    {
        int who = 0;
        int num = 20;
        while (num--)
        {
            // 选择任务
            int task = tm.Selecttask();
            // 选择一个子进程
            channel &ch = _channels[who++];

            who %= _channels.size();

            std::cout << "######################" << std::endl;
            std::cout << "send " << task << " to " << ch.Name() << ", 任务还剩: " << num << std::endl;
            std::cout << "######################" << std::endl;

            // c. 派发任务
            ch.Send(task);

            sleep(1);
        }
    }

    void Cleanprocesspool()
    {
        for (auto &e : _channels)
        {
            e.Close();
            pid_t rid = waitpid(e.Id(), nullptr, 0);

            if (rid > 0)
            {
                std::cout << "process " << rid << " waited sucess" << std::endl;
            }
        }
    }
     void DebugPrint()
    {
        for (auto &c : _channels)
        {
            std::cout << c.Name() << std::endl;
        }
    }


private:
    int _num;
    work_t _work;
    std::vector<channel> _channels;
};
